// enum Direction
// {
//     East,
//     West,
//     North,
//     South
// }
// fn main() {
//     let dir = Direction::North;
//     match dir 
//     {
//         Direction::East =>println!("East"),
//         Direction::North | Direction::South =>{
//             println!("south or norht")
//         } ,
//         _ => println!("west")
//     };
// }
// // 这里我们想去匹配dire对应的枚举类型，因此在match中用三个匹配分支来完全覆盖枚举变量Direction的所有成员类型，有以下几点值得注意：

// // match的匹配必须要穷举出所有可能，因此这里用_来代表未列出的所有可能性
// // match的每一个分支都必须是一个表达式，且所有分支的表达式最终返回值的类型必须相同
// // X | Y，是逻辑运算符或，代表该分支可以匹配X也可以匹配Y，只要满足一个即可
// // 其实match跟其他语言中的switch非常像，_类似于switch中的default。



// fn main() {
//     enum Coin {
//         Penny,
//         Nickel,
//         Dime,
//         Quarter,
//     }
    
//     fn value_in_cents(coin: Coin) -> u8 {
//         match coin {
//             Coin::Penny =>  {
//                 println!("Lucky penny!");
//                 1
//             },
//             Coin::Nickel => 5,
//             Coin::Dime => 10,
//             Coin::Quarter => 25,
//         }
//     }
// }
// // match后紧跟着的是一个表达式，跟if很像，但是if后的表达式必须是一个布尔值，而match后的表达式返回值可以是任意类型，
// // 只要能跟后面的分支中的模式匹配起来即可，这里的coin是枚举Coin类型。




// // 使用match表达式赋值
// // 还有一点很重要，match本身也是一个表达式，因此可以用它来赋值：
// enum IpAddr {
//     Ipv4,
//     Ipv6
//  }
//  fn main() {
//      // let d_panic = Direction::South;
//      let ip1 = IpAddr::Ipv6;
//      let ip_str = match ip1 {
//          IpAddr::Ipv4 => "127.0.0.1",
//          _ => "::1",
//      };
 
//      println!("{}", ip_str);
//  }//因为这里匹配到_分支，所以将"::1"赋值给了ip_str




// //  模式绑定
// //  模式匹配的另外一个重要功能是从模式中取出绑定的值
// #[derive(Debug)]
// enum UsState {
//     Alabama,
//     Alaska,
//     // --snip--
// }
// enum Coin {
//     Penny,
//     Nickel,
//     Dime,
//     Quarter(UsState), // 25美分硬币
// }
// fn main() {
//     fn value_in_cents(coin: Coin) -> u8 {
//         match coin {
//             Coin::Penny => 1,
//             Coin::Nickel => 5,
//             Coin::Dime => 10,
//             Coin::Quarter(state) => { 
//                 println!("State quarter from {:?}!", state);
//                 25
//             },
//         }
//     }
// }
// //   1.上面代码中，在匹配Coin::Quarter(state)模式时，我们把它内部存储的值绑定到了state变量上，
// // 因此state变量就是对应的UsState枚举类型。
// //   2.例如有一个印了阿拉斯加州标记的25分硬币：Coin::Quarter(UsState::Alaska)), 
// // 它在匹配时，state变量将被绑定UsState::Alaska的枚举值

//更复杂的例子
enum Action{
    Say(String),
    MoveTo(i32,i32),
    ChangeColorRGB(u16,u16,u16)
}

fn main()
{
    let actions = [
        Action::Say("hello Rust".to_string()),
        Action::MoveTo(1,2),
        Action::ChangeColorRGB(255,255,0)
    ];
    for action in actions
    {
        match action
        {
            Action::Say(s)  => {
                println!("{}",s);
            }
            Action::MoveTo(x,y) =>{
                println!("point from (0,0) move ({},{})",x,y);
            }
            Action::ChangeColorRGB(r,g,_) =>{
                println!("change color in to '(r:{},g:{}.b:0)','b' has been ignored",r,g);
            }
        };
    }
}


// 穷尽匹配
// match的匹配必须穷尽所有情况.
enum Direction {
    East,
    West,
    North,
    South,
}
fn main() {
    let dire = Direction::South;
    match dire {
        Direction::East => println!("East"),
        Direction::North | Direction::South => {
            println!("South or North");
        },
    };
}//我们没有处理Direction::West的情况



// _ 通配符
// 当我们不想在匹配的时候列出所有值的时候，可以使用Rust提供的一个特殊模式，
// 例如，u8 可以拥有 0 到 255 的有效的值，但是我们只关心 1、3、5 和 7 这几个值，
// 不想列出其它的 0、2、4、6、8、9 一直到 255 的值。
// 那么, 我们不必一个一个列出所有值, 因为可以使用使用特殊的模式 _ 替代：
fn main() {
    let some_u8_value = 0u8;
    match some_u8_value {
        1 => println!("one"),
        3 => println!("three"),
        5 => println!("five"),
        7 => println!("seven"),
        _ => (),
    }
}
//将_其放置于其他分支后，_将会匹配所有遗漏的值。()表示啥都不做的意思，所以当匹配到_后，什么也不会发生。




// if let匹配
// 有时会遇到只有一个模式的值需要被处理，其它值直接忽略的场景，就用 if let
fn main()
{
    let v = Some(0u8);
    match v {
        Some(3) => println!("three"),
        _ => (),
    }


    //上面的代码用match不够简洁，因为只针对一个值进行判断
    if let some(3) = v{
        println!{"three"};
    }//if let还可以搭配 else 来使用
    else{
        println!("others");
    }
}



// matches!宏
// Rust标准库中提供了一个非常实用的宏:matches!，它可以将一个表达式跟模式进行匹配，然后返回匹配的结果true or false。
enum MyEnum {
    Foo,
    Bar
}
fn main() {
    let v = vec![MyEnum::Foo,MyEnum::Bar,MyEnum::Foo];
    // 现在如果想对v进行过滤，只保留类型是MyEnum::Foo的元素，你可能想这么写：
    //err  v.iter().filter(|x| x == MyEnum::Foo);
    v.iter().filter(|x| matches!(x, MyEnum::Foo));
}



// 变量覆盖
// 无论是是match还是if let，他们都可以在模式匹配时覆盖掉老的值，绑定新的值:
fn main() {
    let age = Some(30);
    println!("在匹配前，age是{:?}",age);
    if let Some(age) = age {
        println!("匹配出来的age是{}",age);
    }
 
    println!("在匹配后，age是{:?}",age);
 }

//  对于match类型也是如此:
 fn main() {
    let age = Some(30);
    println!("在匹配前，age是{:?}",age);
    match age {
        Some(age) =>  println!("匹配出来的age是{}",age),
        _ => ()
    }
    println!("在匹配后，age是{:?}",age);
 }







